"""
FTP服务端代码
"""
from threading import Thread
from socket import *
import os
import time


class Handle:
    def __init__(self, filename, conn):
        self.filename = filename
        self.conn = conn

    def do_request(self):
        while True:
            request = self.conn.recv(128).decode()  # 收请求
            if request == "QUIT" or not request:
                break
            tmp = request.split(" ")  # 解析请求查看请求类型
            if request == "LIST":
                self.do_list()
            elif tmp[0] == "GET":
                self.do_get(tmp[1])
            elif tmp[0] == "PUT":
                self.do_put(tmp[1])

    def do_list(self):
        files = os.listdir(self.filename)  # 读取文件库所有文件
        if files:
            request = "OK " + "\n" + "\n".join(files)  # 发送响应、用join函数把列表的所有元素拼接为一个大的字符串
        else:
            request = "FAIL"
        self.conn.send(request.encode())

    def do_get(self, filename):
        try:
            fr = open(self.filename + filename, "rb")  # 读取需要下载文件内容
        except:
            self.conn.send(b"FAIL")  # 文件不存在
        else:
            self.conn.send(b"OK")  # 发送响应延迟避免粘包
            time.sleep(0.1)
            while True:
                data = fr.read(1024)  # 读取文件内容 读到空结束
                if not data:
                    break
                self.conn.send(data)  # 发送读取到内容
            fr.close()
            time.sleep(0.1)  # 文件读取完毕延迟发送结束标志避免粘包(##)
            self.conn.send(b"##")  # 结束标志

    def do_put(self, filename):
        if os.path.exists(self.filename + filename):  # 如果为真表示文件已存在发送响应
            self.conn.send(b"EXISIS")
        else:
            self.conn.send(b"OK")
            fw = open(self.filename + filename, "wb")  # 文件不存在发送响应，循环接收将数据写入文件
            while True:
                data = self.conn.recv(1024)
                if data == b"##":
                    break
                fw.write(data)
            fw.close()


class MyThreading(Thread):
    def __init__(self, conn, filename):  # 子套接字和文件库名
        self.conn = conn
        self.filename = filename
        # self.handle = Handle('../day05/', conn)
        self.handle = Handle(filename, conn)
        super().__init__()

    def run(self, ):  # 具体逻辑处理跨类调用
        self.handle.do_request()
        self.conn.close()


class FTPServer:
    def __init__(self, host, port, filename):
        self.host = host
        self.port = port
        self.frs = filename
        self.address = (host, port)
        self.sock = self.create_sock()

    def create_sock(self):
        sock = socket()
        sock.bind(self.address)
        return sock

    def main(self):
        self.sock.listen(5)  # 监听
        print("Listen to port %d" % self.port)
        while True:
            conn, addr = self.sock.accept()  # 多线程并发
            print("From addr", addr)
            thread = MyThreading(conn, self.frs)  # 子套接字，文件库
            thread.start()


if __name__ == '__main__':
    ftp_server = FTPServer("0.0.0.0", 1216, '../day05/')   # host,port,file(文件库)
    ftp_server.main()
